package com.ruoyi.common.utils.wx;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.ruoyi.common.exception.wx.WeChatApiException;
import com.ruoyi.common.exception.wx.WxDecryptionException;
import com.ruoyi.common.utils.http.Axios;
import com.ruoyi.project.system.domain.dto.WxSessionKeyDto;
import com.ruoyi.project.system.domain.dto.WxUserInfoDto;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestClientException;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.util.Base64;

/**
 * @author 翰林学士
 * @version 1.0
 * @email RenZetong@Outlook.com
 * Create by 2025-02-08 09:28:41
 * 微信小程序工具类
 */
@Component
public class WeChatMiniProgramUtil {

    @Value("${wx.appid}" )
    private String appId;

    @Value("${wx.secret}" )
    private String secret;

    /**
     * 获取微信openId和身份信息
     *
     * @param code 请求码
     */
    public WxSessionKeyDto getSessionKeyAndOpenId(String code) throws WeChatApiException {

        // 构造请求URL
        String url = String.format(
                "https://api.weixin.qq.com/sns/jscode2session?appid=%s&secret=%s&js_code=%s&grant_type=authorization_code" ,
                appId, secret, code);

        try {
            // 发送Get请求
            ResponseEntity<String> response = Axios.get(url, null, null, String.class);

            // 解析数据
            WxSessionKeyDto sessionData = new ObjectMapper().readValue(response.getBody(), WxSessionKeyDto.class);
            if (sessionData.getErrcode() != null && sessionData.getErrcode() != 0) {
                throw new WeChatApiException("微信接口错误:" + sessionData.getErrmsg(), sessionData.getErrcode());
            }
            if (sessionData.getOpenid() == null || sessionData.getSession_key() == null) {
                throw new WeChatApiException("微信返回数据不完整" , 500);
            }
            return sessionData;

        } catch (RestClientException e) {
            throw new WeChatApiException("网络请求异常:" + e.getMessage(), 500);
        } catch (Exception e) {
            throw new WeChatApiException("数据解析异常:" + e.getMessage(), 500);
        }
    }

    /**
     * 解密用户加密数据
     *
     * @param encryptedData 加密数据
     * @param iv            加密算法的初始向量
     * @param sessionKey    会话密钥
     * @return 用户信息
     * @throws WxDecryptionException 解密异常
     */
    public WxUserInfoDto decryptUserInfo(String encryptedData, String iv, String sessionKey) throws WxDecryptionException {
        try {
            // Base64解码
            byte[] encryptedDataBytes = Base64.getDecoder().decode(encryptedData);
            byte[] ivBytes = Base64.getDecoder().decode(iv);
            byte[] sessionKeyBytes = Base64.getDecoder().decode(sessionKey);

            // 初始化AES算法
            SecretKeySpec secretKeySpec = new SecretKeySpec(sessionKeyBytes, "AES" );
            IvParameterSpec ivParameterSpec = new IvParameterSpec(ivBytes);

            // 配置解密模式
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding" );
            cipher.init(Cipher.DECRYPT_MODE, secretKeySpec, ivParameterSpec);

            // 执行解密
            byte[] decryptedBytes = cipher.doFinal(encryptedDataBytes);
            String decryptedData = new String(decryptedBytes, StandardCharsets.UTF_8);

            // 将JSON转换为对象
            return new ObjectMapper().readValue(decryptedData, WxUserInfoDto.class);
        } catch (Exception e) {
            throw new WxDecryptionException("数据解密失败: " + e.getMessage());
        }
    }
}
